package com.bsoft.gol.hcs.specialist.dao;

import ctd.controller.exception.ControllerException;
import ctd.persistence.DAOFactory;
import ctd.persistence.annotation.DAOMethod;
import ctd.persistence.annotation.DAOParam;
import ctd.persistence.support.hibernate.HibernateSupportDelegateDAO;
import ctd.persistence.support.hibernate.template.AbstractHibernateStatelessResultAction;
import ctd.persistence.support.hibernate.template.HibernateSessionTemplate;
import ctd.persistence.support.hibernate.template.HibernateStatelessResultAction;
import ctd.util.converter.ConversionUtils;
import com.bsoft.gol.hcs.enumcase.ConditionFilterMethodEnum;
import com.bsoft.gol.hcs.enumcase.FollowTypeEnum;
import com.bsoft.gol.hcs.enumcase.InspectIndexEnum;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.StatelessSession;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.transform.Transformers;
import com.bsoft.gol.hcs.specialist.bean.request.GroupChronicRecordQo;
import com.bsoft.gol.hcs.specialist.bean.request.QueryOperativeListRequest;
import com.bsoft.gol.hcs.specialist.bean.response.CrucialRecordResponse;
import com.bsoft.gol.hcs.specialist.bean.response.CrucialTimeRecordList;
import com.bsoft.gol.hcs.specialist.bean.response.FactorData;
import com.bsoft.gol.hcs.specialist.bean.response.PatientIndexListResp;
import com.bsoft.gol.hcs.specialist.entity.FollowUpRouteDetailFactorRelation;
import com.bsoft.gol.hcs.specialist.entity.FusAnswerCheckReportInfo;
import com.bsoft.gol.hcs.specialist.entity.FusCrucialIndexRecord;
import com.bsoft.gol.hcs.utils.CommonUtils;
import com.bsoft.gol.hcs.utils.DateUtil;

import java.util.*;

import static com.bsoft.gol.hcs.enumcase.ConditionFilterMethodEnum.getEnumByKey;
import static com.bsoft.gol.hcs.enumcase.InspectIndexEnum.*;

/**
 * @author tongtp
 * @version v0.1
 * @className FusAnswerCheckReportInfoDAO
 * @description
 * @create 2020-07-31 15:02
 **/
public abstract class FusAnswerCheckReportInfoDAO extends HibernateSupportDelegateDAO<FusAnswerCheckReportInfo> {

    /**
     * @param reportId
     * @throws
     * @description: 根据表单答案唯一记录id查询
     * @return: specialist.entity.FusAnswerCheckReportInfo
     * @author: tongtp
     * @date: 2020/8/4 17:57
     */
    @DAOMethod(sql = " from FusAnswerCheckReportInfo where reportId = :reportId")
    public abstract FusAnswerCheckReportInfo getByReportId(@DAOParam("reportId") String reportId);

    /**
     * @param answerTime
     * @throws
     * @description: 更新检查报告指标结果内容
     * @return: java.util.List<java.lang.Long>
     * @author: tongtp
     * @date: 2020/7/31 16:59
     */
    public Integer updateIndexResultContent(final Date answerTime) {
        HibernateStatelessResultAction<Integer> action =
                new AbstractHibernateStatelessResultAction<Integer>() {
                    @Override
                    public void execute(StatelessSession ss) throws Exception {
                        StringBuilder sqlBuilder = new StringBuilder();
                        sqlBuilder.append("update fus_answer_check_report_info AS a set a.index_result_content = " +
                                "(select b.index_result_content from fus_index_result AS b where b.index_id = a" +
                                ".item_id AND b.index_result_type = 1 AND b.lower_limit <= a.item_content AND b" +
                                ".upper_limit >= a.item_content) where index_result_content IS NULL AND a" +
                                ".answer_time" +
                                " " +
                                ">= :answerTime");

                        Query query = ss.createSQLQuery(sqlBuilder.toString());
                        query.setParameter("answerTime", answerTime);

                        int executeUpdate = query.executeUpdate();

                        sqlBuilder.setLength(0);
                        sqlBuilder.append("update fus_answer_check_report_info AS a set a.index_result_content = " +
                                "(select b.index_result_content from fus_index_result AS b where b.index_id = a" +
                                ".item_id AND b.index_result_type = 2 AND b.index_description = a.item_content) " +
                                "where" +
                                " " +
                                "index_result_content IS NULL AND a" +
                                ".answer_time" +
                                " " +
                                ">= :answerTime");
                        query = ss.createSQLQuery(sqlBuilder.toString());
                        query.setParameter("answerTime", answerTime);

                        executeUpdate += query.executeUpdate();
                        setResult(executeUpdate);
                    }
                };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }

    public List<PatientIndexListResp> queryIndexListByPatientId(final QueryOperativeListRequest request) {
        HibernateStatelessResultAction<List<PatientIndexListResp>> action = new AbstractHibernateStatelessResultAction<List<PatientIndexListResp>>() {
            @Override
            public void execute(StatelessSession ss) {
                StringBuffer stringBuffer = getIndexListByPatientId(request);
                SQLQuery sqlQuery = ss.createSQLQuery(stringBuffer.toString());
                sqlQuery.setParameter("patientId", request.getPatientId());
                sqlQuery.setParameter("itemId", request.getItemId());
                int first = request.getPageNo() > 0 ? (request.getPageNo() - 1) * request.getPageSize() : 0;
                sqlQuery.setFirstResult(first);
                sqlQuery.setMaxResults(request.getPageSize());
                sqlQuery.setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP);
                List<Map> dbList = sqlQuery.list();
                List<PatientIndexListResp> listResps = new ArrayList<>();
                for (Map map : dbList) {
                    listResps.add(ConversionUtils.convert(map, PatientIndexListResp.class));
                }
                setResult(listResps);
            }
        };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }

    private StringBuffer getIndexListByPatientId(QueryOperativeListRequest request) {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("select * from ( ");
        stringBuffer.append(" (select item_id itemId, item_name   itemName,item_content itemContent ,report_time reportTime, index_result_content reportStat,  " +
                "  disease_type_id  diseaseTypeId, disease_type_name diseaseTypeName, '' resultUnit  from fus_answer_check_report_info d " +
                "   WHERE  patient_id =:patientId ");
        stringBuffer.append(" and item_id =:itemId order by report_time desc ) ");


        stringBuffer.append(" UNION   ");

        stringBuffer.append(" (select item_id itemId, item_name   itemName, result itemContent ,report_time reportTime, index_result_content reportStat,  " +
                "  disease_type_id  diseaseTypeId, disease_type_name diseaseTypeName, result_unit resultUnit  from fus_answer_inspection_report_info  " +
                "   WHERE  patient_id =:patientId ");
        stringBuffer.append(" and item_id =:itemId order by report_time desc ) ");

        stringBuffer.append(" UNION " +
                " ( " +
                "  SELECT " +
                "   a.hpi_code AS itemId, " +
                "   a.hpi_name AS itemName, " +
                "   a.hpi_value AS itemContent, " +
                "   b.measure_date AS reportTime, " +
                "   CASE a.result_status WHEN '1' THEN '正常' WHEN '2' THEN '偏高' WHEN '3' THEN '偏低' ELSE '未知' END AS reportStat, " +
                "   '' AS diseaseTypeId, " +
                "   '' AS diseaseTypeName, " +
                "   a.hpi_unit AS result_unit " +
                "  FROM " +
                "   ods_hm_detail a, " +
                "   ods_hm_record b, " +
                "   fus_disease_relate_list c, " +
                "   fus_crucial_index_record d, " +
                "   fus_team_chronic_group_record e " +
                "  WHERE " +
                "   a.hm_record_id = b.hm_record_id " +
                "  AND a.index_code = d.index_code " +
                "  AND c.relate_type = '4' " +
                "  AND d.index_id = c.relate_record_id " +
                "  AND c.disease_type_id = e.chronic_disease_id " +
                "  AND b.mpi_id = e.person_id  " +
                "  AND e.patient_id =:patientId " +
                "  AND d.index_id =:itemId order by b.measure_date desc " +
                " ) ");
        stringBuffer.append(" ) f  order by reportTime desc");

        return stringBuffer;
    }

    /**
     * 获取检查的关联指标信息
     *
     * @param qo
     * @return
     */
    public List<CrucialRecordResponse> queryAnswerExamReportInfo(GroupChronicRecordQo qo) {
        HibernateStatelessResultAction<List<CrucialRecordResponse>> action = new AbstractHibernateStatelessResultAction<List<CrucialRecordResponse>>() {
            @Override
            public void execute(StatelessSession ss) throws Exception {
                StringBuilder sqlBuilder = new StringBuilder();
                sqlBuilder.append("SELECT DISTINCT  " +
                        "  item_id AS indexType,  " +
                        "  item_name AS indexName   " +
                        "FROM  " +
                        "  fus_answer_check_report_info  where card_number =:idCard and disease_type_id =:diseaseTypeId ");
                sqlBuilder.append(" and answer_time >=:beginTime and answer_time <=:endTime group by item_id,item_name ");
                Query query = ss.createSQLQuery(sqlBuilder.toString());
                query.setParameter("idCard", qo.getIdCard());
                query.setParameter("diseaseTypeId", qo.getDiseaseTypeId());
                query.setParameter("beginTime", qo.getBeginTime()+" 00:00:00");
                query.setParameter("endTime", qo.getEndTime()+" 23:59:59");
                query.setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP);
                List<Map> list = query.list();
                List<CrucialRecordResponse> voList = new ArrayList<>();
                if (CommonUtils.isNotEmpty(list)) {
                    for (Map map : list) {
                        voList.add(ConversionUtils.convert(map, CrucialRecordResponse.class));
                    }
                } else {
                    voList = new ArrayList<>();
                }
                setResult(voList);
            }
        };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }

    /**
     * 根据用户和病种查询ReportId
     *
     * @param diseaseTypeId
     * @param patientId
     * @param patientMedicalCardType
     * @param patientMedicalCardNumber
     * @param cardType
     * @param cardNumber
     * @return java.util.List<java.lang.String>
     * @throws
     * @author tongtp
     * @date 2021/12/29 13:41
     */
    public List<String> queryReportId(Long diseaseTypeId, String patientId,
                                      Integer patientMedicalCardType, String patientMedicalCardNumber,
                                      String cardType, String cardNumber) {
        HibernateStatelessResultAction<List<String>> action =
                new AbstractHibernateStatelessResultAction<List<String>>() {
                    @Override
                    public void execute(StatelessSession ss) throws Exception {
                        StringBuilder sqlBuilder = new StringBuilder();
                        sqlBuilder.append("select report_id from fus_answer_check_report_info" +
                                "  where disease_type_id = :diseaseTypeId ");
                        sqlBuilder.append(" and ( ");
                        if (CommonUtils.isNotNull(patientId)) {
                            sqlBuilder.append(" patient_id = :patientId ");
                        }
                        if (CommonUtils.isNotNull(patientMedicalCardType) && CommonUtils.isNotNull(patientMedicalCardNumber)) {
                            sqlBuilder.append("  or (patient_medical_card_type = :patientMedicalCardType and" +
                                    " patient_medical_card_number = :patientMedicalCardNumber) ");
                        }
                        if (CommonUtils.isNotNull(cardType) && CommonUtils.isNotNull(cardNumber)) {
                            sqlBuilder.append("  or (card_type = :cardType and" +
                                    " card_number = :cardNumber) ");
                        }
                        sqlBuilder.append(" ) ");
                        Query query = ss.createSQLQuery(sqlBuilder.toString());
                        query.setParameter("diseaseTypeId", diseaseTypeId);
                        if (CommonUtils.isNotNull(patientId)) {
                            query.setParameter("patientId", patientId);
                        }
                        if (CommonUtils.isNotNull(patientMedicalCardType) && CommonUtils.isNotNull(patientMedicalCardNumber)) {
                            query.setParameter("patientMedicalCardType", patientMedicalCardType);
                            query.setParameter("patientMedicalCardNumber", patientMedicalCardNumber);
                        }
                        if (CommonUtils.isNotNull(cardType) && CommonUtils.isNotNull(cardNumber)) {
                            query.setParameter("cardType", cardType);
                            query.setParameter("cardNumber", cardNumber);
                        }
                        List list = query.list();
                        List<String> voList;
                        if (CommonUtils.isNotEmpty(list)) {
                            voList = list;
                        } else {
                            voList = new ArrayList<>();
                        }
                        setResult(voList);
                    }
                };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }

    /**
     * 编辑器检查数据时间集合
     *
     * @param qo
     * @param itemName
     * @return
     */
    public List<CrucialTimeRecordList> queryAnswerExamReportTimeInfo(GroupChronicRecordQo qo, String itemName) {
        HibernateStatelessResultAction<List<CrucialTimeRecordList>> action =
                new AbstractHibernateStatelessResultAction<List<CrucialTimeRecordList>>() {
                    @Override
                    public void execute(StatelessSession ss) throws Exception {
                        StringBuilder sqlBuilder = new StringBuilder();
                        sqlBuilder.append("SELECT " +
                                " item_id AS indexType, " +
                                " item_name AS indexName, " +
                                " item_content as indexResultContent, " +
                                " answer_time as crucialTime  " +
                                "FROM " +
                                " fus_answer_check_report_info  " +
                                "where item_name =:itemName and card_number =:idCard and disease_type_id " +
                                "=:diseaseTypeId ");
                        sqlBuilder.append(" and answer_time >=:beginTime and answer_time <=:endTime order by answer_time ");
                        Query query = ss.createSQLQuery(sqlBuilder.toString());
                        query.setParameter("itemName", itemName);
                        query.setParameter("idCard", qo.getIdCard());
                        query.setParameter("diseaseTypeId", qo.getDiseaseTypeId());
                        query.setParameter("beginTime", qo.getBeginTime()+" 00:00:00");
                        query.setParameter("endTime", qo.getEndTime()+" 23:59:59");
                        query.setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP);
                        List<Map> list = query.list();
                        List<CrucialTimeRecordList> voList = new ArrayList<>();
                        if (CommonUtils.isNotEmpty(list)) {
                            for (Map map : list) {
                                voList.add(ConversionUtils.convert(map, CrucialTimeRecordList.class));
                            }
                        } else {
                            voList = new ArrayList<>();
                        }
                        setResult(voList);
                    }
                };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }

    public List<FactorData> executeFactorForRelatedIndicators(FollowUpRouteDetailFactorRelation factorRelation, Date startTime, Date endTime, List<String> patientIdList, Byte isLoopExecute, Long routeDetailId, String followType) {
        HibernateStatelessResultAction<List<FactorData>> action =
                new AbstractHibernateStatelessResultAction<List<FactorData>>() {
                    @Override
                    public void execute(StatelessSession ss) throws Exception {
                        StringBuilder sqlBuilder = new StringBuilder();
                        sqlBuilder.append("select patientId,indexRecordId,indexCode,indexName,indexResult,reportTime," +
                                "dataSource from (");
                        sqlBuilder.append("SELECT e.patient_id as patientId, '2' as dataSource, ");
                        sqlBuilder.append("e.item_id AS indexRecordId, e.exam_type_code AS indexCode, e" +
                                ".exam_type_name AS indexName,");
                        sqlBuilder.append("e.index_result_content AS indexResult,  e.report_time AS reportTime ");
                        sqlBuilder.append(" FROM fus_answer_check_report_info e  where e.item_id =:indexResultId ");
                        //条件筛选方法：1 范围(包含边界) 2 等于 3 大于 4 小于 5 大于等于 6 小于等于，7包含，8不包含 9 Between
                        Byte conditionFilterMethod = Byte.valueOf(factorRelation.getCompareSign());
                        //检查的，要查询指标编码
                        FusCrucialIndexRecordDAO crucialIndexRecordDAO =
                                DAOFactory.getDAO(FusCrucialIndexRecordDAO.class);
                        FusCrucialIndexRecord fusCrucialIndexRecord =
                                crucialIndexRecordDAO.get(factorRelation.getFactorId());
                        if (fusCrucialIndexRecord == null) {
                            throw new ControllerException("不存在的关联指标，无法完成检索");
                        }
                        InspectIndexEnum indexEnum =
                                InspectIndexEnum.getEnumByKey(fusCrucialIndexRecord.getIndexCode());
                        if (indexEnum == null) {
                            setResult(Collections.emptyList());
                            return;
//                            throw new ControllerException("未实现的关联指标，无法完成检索");
                        }
                        ConditionFilterMethodEnum methodEnum = getEnumByKey(conditionFilterMethod);
                        //检查只有文本和定性(阴阳性)
                        if (IMAGE_DIAGNOSIS.equals(indexEnum)) {
                            switch (methodEnum) {
                                case CONTAIN:
                                    sqlBuilder.append(" and e.index_result_content like :factorResultOne");
                                    break;
                                case NOT_INCLUDED:
                                    sqlBuilder.append(" and e.index_result_content not like :factorResultOne");
                                    break;
                                default:
                                    throw new ControllerException("不合法的运算符");
                            }
                        }
                        if (EXAM_FINDING.equals(indexEnum)) {
                            switch (methodEnum) {
                                case CONTAIN:
                                    sqlBuilder.append(" and e.index_result_content like :factorResultOne");
                                    break;
                                case NOT_INCLUDED:
                                    sqlBuilder.append(" and e.index_result_content not like :factorResultOne");
                                    break;
                                default:
                                    throw new ControllerException("不合法的运算符");
                            }
                        }
                        if (YIN_YANG.equals(indexEnum)) {
                            switch (methodEnum) {
                                case CONTAIN:
                                    sqlBuilder.append(" and e.malignant in (:factorResultList) ");
                                    break;
                                case NOT_INCLUDED:
                                    sqlBuilder.append(" and e.malignant not in (:factorResultList) ");
                                    break;
                                default:
                                    throw new ControllerException("不合法的运算符");
                            }
                        }

                        if (CommonUtils.isNotEmpty(startTime)) {
                            sqlBuilder.append(" and e.report_time>=:startTime");
                        }
                        if (CommonUtils.isNotEmpty(endTime)) {
                            sqlBuilder.append(" and e.report_time<=:endTime");
                        }
                        if (CommonUtils.isNotEmpty(patientIdList)) {
                            sqlBuilder.append(" and patient_id in(:patientIdList) ");
                        }
                        sqlBuilder.append(") AS  m ");
                        //循环执行机制 0 不执行 1 执行
                        if (FollowTypeEnum.FUS_SPECIALIST.getType().equals(followType) && null != isLoopExecute && isLoopExecute == 1) {
                            sqlBuilder.append(" LEFT JOIN fus_factor_data_record f  ON f.patient_id = m.patientId   " +
                                    "AND f.route_detail_id = :routeDetailId AND f.index_record_id = m.indexRecordId " +
                                    "WHERE f.id IS NULL  ");
                        }
                        Query query = ss.createSQLQuery(sqlBuilder.toString());
                        query.setParameter("indexResultId", factorRelation.getIndexResultId());
                        //检查只有文本和定性(阴阳性)
                        if (IMAGE_DIAGNOSIS.equals(indexEnum) || EXAM_FINDING.equals(indexEnum)) {
                            query.setParameter("factorResultOne", "%" + factorRelation.getFactorResultOne() + "%");
                        }
                        if (YIN_YANG.equals(indexEnum)) {
                            //定性结果-只会有包含in 和不包含 not in
                            String[] strings = factorRelation.getFactorResultOne().split(",");
                            List<String> factorResultList = Arrays.asList(strings);
                            query.setParameterList("factorResultList", factorResultList);
                        }
                        if (CommonUtils.isNotEmpty(startTime)) {
                            query.setParameter("startTime", DateUtil.dateFormate(startTime, "yyyy-MM-dd"));
                        }
                        if (CommonUtils.isNotEmpty(endTime)) {
                            query.setParameter("endTime", DateUtil.dateFormate(endTime, "yyyy-MM-dd")+" 23:59:59");
                        }
                        if (CommonUtils.isNotEmpty(patientIdList)) {
                            query.setParameterList("patientIdList", patientIdList);
                        }
                        if (FollowTypeEnum.FUS_SPECIALIST.getType().equals(followType) && null != isLoopExecute && isLoopExecute == 1) {
                            query.setParameter("routeDetailId", routeDetailId);
                        }
                        query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);

                        List<Map> list = query.list();
                        List<FactorData> voList = new ArrayList<>();
                        if (CommonUtils.isNotEmpty(list)) {
                            for (Map map : list) {
                                voList.add(ConversionUtils.convert(map, FactorData.class));
                            }
                        } else {
                            voList = new ArrayList<>();
                        }
                        setResult(voList);
                    }
                };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }
}
